import { InjectionToken, Disposable, Lifecycle, scoped } from "tsyringe"
import { tryGetAll } from "../utils/tryGetAll";
import { IListener } from "../core/listener";
import { LISTENERS } from "../tokens/core";
import { EventEmitter } from "events";
@scoped(Lifecycle.ContainerScoped)
export class Sender implements Disposable {
    private listeners: IListener[] = [];
    handler: any;
    handlers: any[] = [];
    emitters: EventEmitter[] = []
    onInit(): void {
        this.listeners = tryGetAll(LISTENERS)
        this.listeners.map(listener => {
            events.broadcast.on(listener.type as string, listener.on)
        })
    }
    create() {
        const emitter = events.emitter()
        this.emitters.push(emitter)
        return emitter;
    }
    send<T>(type: string | InjectionToken<T>, payload: T) {
        events.broadcast.emit(type as string, payload)
    }
    emit<T>(type: string | InjectionToken<T>, payload: T) {
        events.broadcast.emit(type as string, payload)
    }
    on<T>(type: string | InjectionToken<T>, fn: (data: T) => void) {
        this.handlers.push({ type, handler: fn })
        events.broadcast.on(type as string, fn)
    }
    dispose(): void | Promise<void> {
        this.listeners.map(listener => {
            events.broadcast.removeListener(listener.type as string, listener.on)
        });
        this.handlers.map(({ type, handler }) => {
            events.broadcast.removeListener(type, handler);
        })
        this.emitters.map(e => e.removeAllListeners())
    }
}
